home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / util / catchSignals.c next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  9.9 KB  |  384 lines

  1. /*
  2.  *   $RCSfile: catchSignals.c,v $  
  3.  *   $Revision: 1.2 $  
  4.  *   $Date: 1996/05/04 23:51:56 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37. #include "queue_consist.h"
  38. #include "sysdefs.h"
  39. #include "ess.h"
  40. #include "checking.h"
  41. #include "list.h"
  42. #include "error.h"
  43. #include "sysdefs.h"
  44. #include "tid.h"
  45. #include "pool.h"
  46. #include "io.h"
  47. #include "bitvec.h"
  48. #include "lock.h"
  49. #include "object.h"
  50. #include "msgdefs.h"
  51. #include "disk.h"
  52. #include "thread.h"
  53. #include "semaphore.h"
  54. #include "latch.h"
  55. #include "bf.h"
  56. #include "link.h"
  57. #include "volume.h"
  58. #include "trace.h"
  59. #include "msgvector.h"
  60.  
  61. #include "disk_funcs.h"
  62. #include "server_util_funcs.h"
  63. #include "adminmsg.h"
  64. #include "admin_funcs.h"
  65.  
  66. #ifdef linux
  67. #include <bsd/signal.h>
  68. #endif
  69.  
  70. static void unexpected(int,int);
  71. static void quiet(int,int);
  72. /* export this */ void cont(int,int);
  73.  
  74. static int mypg;
  75. static int ppid;
  76. static int devttyfd;
  77.  
  78. /* whatever is not included here, doesn't get touched. */
  79. struct siginfo {
  80.     int     sig;
  81.     char *string;
  82.     int     error_type;
  83.     void (*sv_handler)(int,int);
  84. } siginfo[] = {
  85.     { 0,        "<none>",     TYPE_FATAL,     unexpected },
  86.     { SIGHUP,    "SIGHUP",     TYPE_FATAL,     unexpected },
  87.     { SIGINT,    "SIGINT",     TYPE_QUIET,      quiet }, /* ^C */
  88.     { SIGQUIT,    "SIGQUIT",    TYPE_FATAL,  unexpected },
  89.     { SIGILL,    "SIGILL",    TYPE_FATAL,  unexpected },
  90.     { SIGTRAP,    "SIGTRAP",    TYPE_FATAL,  unexpected },
  91.     { SIGIOT,    "SIGIOT",    TYPE_FATAL,  unexpected },
  92. #ifndef linux
  93.     { SIGEMT,    "SIGEMT",    TYPE_FATAL,  unexpected },
  94. #endif linux
  95.     { SIGFPE,    "SIGFPE",    TYPE_FATAL,  unexpected },
  96.     { SIGKILL,    "SIGKILL",    0,          (void (*)(int,int))SIG_DFL },
  97.     { SIGBUS,    "SIGBUS",    TYPE_FATAL,  unexpected },
  98.     { SIGSEGV,    "SIGSEGV",    TYPE_FATAL,  (void (*)(int,int))SIG_DFL }, /* unexpected */
  99. #ifndef linux
  100.     { SIGSYS,    "SIGSYS",    TYPE_FATAL,  unexpected } ,
  101. #endif linux
  102.     { SIGPIPE,    "SIGPIPE",    TYPE_QUIET,      quiet }, /* diskproc exited? */
  103.     { SIGALRM,    "SIGALRM",    0,          (void (*)(int,int))SIG_DFL },
  104.     { SIGTERM,    "SIGTERM",    0,          (void (*)(int,int))SIG_DFL },
  105.     { SIGURG,    "SIGURG",    TYPE_FATAL,  unexpected },
  106.     { SIGSTOP,    "SIGSTOP",    0,          (void (*)(int,int))SIG_DFL },
  107.     { SIGTSTP,    "SIGTSTP",    0,          (void (*)(int,int))SIG_DFL },
  108.     { SIGCONT,    "SIGCONT",    0,          cont },
  109.     { SIGCHLD,    "SIGCHLD",    0,          (void (*)(int,int))SIG_DFL },
  110.     { SIGTTIN,    "SIGTTIN",    0,          cont },
  111.     { SIGTTOU,    "SIGTTOU",    0,          (void (*)(int,int))SIG_IGN },
  112.     { SIGIO,    "SIGIO",    TYPE_FATAL,  unexpected },
  113. #ifdef hpux
  114.     { SIGPWR,   "SIGPWR",   TYPE_FATAL,  unexpected },
  115.     /* this signal cannot be caught in HP-UX */
  116.     /*{ _SIGRESERVE,    "SIGRESERVE",   TYPE_FATAL,  unexpected },*/
  117. #else
  118.     { SIGXCPU,  "SIGXCPU",  TYPE_FATAL,  unexpected },
  119.     { SIGXFSZ,  "SIGXFSZ",  TYPE_FATAL,  unexpected },
  120. #endif hpux
  121.     { SIGVTALRM,"SIGVTALRM",TYPE_FATAL,  unexpected },
  122.     { SIGPROF,    "SIGPROF",    0,          (void (*)(int,int))SIG_DFL },
  123.     { SIGWINCH,    "SIGWINCH",    0,          (void (*)(int,int))SIG_DFL },
  124. #ifndef linux
  125.     { SIGLOST,    "SIGLOST",    TYPE_FATAL,  unexpected },
  126. #endif linux
  127.     { SIGUSR1,    "SIGUSR1",    TYPE_FATAL,  unexpected },
  128.     { SIGUSR2,    "SIGUSR2",    TYPE_FATAL,  unexpected },
  129.     { 0, 0, 0, 0}
  130. };
  131.  
  132. static void 
  133. doit(
  134.     int sig,
  135.     int code
  136. )
  137. {
  138.     TRPRINT(TR_INIT, TR_LEVEL_1, ("sig %d, code %d", sig, code));
  139.     if ((siginfo[sig].error_type == TYPE_FATAL) ||
  140.         (siginfo[sig].error_type == TYPE_STOP) ) {
  141.         /* make sure that you can at least use ^C or equivalent */ 
  142.         unCatchAbortSignal(SIGINT);
  143.         /* for the sake of catching some error in admin_ShutServer */
  144.         unCatchAbortSignal(SIGSEGV);
  145.         unCatchAbortSignal(SIGILL);
  146.     }
  147.     SM_ERROR(siginfo[sig].error_type, esmUNIXSIGNAL);
  148. } /* doit */
  149.  
  150. static void
  151. quiet(
  152.     int sig,
  153.     int code
  154. )
  155. {
  156.     /* print message only if tracing is on */
  157.     TRPRINT(TR_INIT, TR_LEVEL_1, ("sig %d, code %d", sig, code));
  158.  
  159.     doit(sig,code);
  160. }
  161.  
  162.  
  163. static void 
  164. unexpected(
  165.     int sig,
  166.     int code
  167. )
  168. {
  169.     fprintf(stderr, "SERVER : signal %s code %d\n", siginfo[sig].string, code);
  170.     doit(sig,code);
  171. }
  172.  
  173. static BOOL
  174. isbg()
  175. {
  176.     int ctermpg = 0;
  177.     BOOL result;
  178.  
  179.     if(RunInBackground)  /* pretend we are */
  180.         return TRUE;
  181.  
  182.     if(ioctl(devttyfd, TIOCGPGRP, &ctermpg) < 0) {
  183.         if((errno == ENOTTY) || (errno == EOPNOTSUPP)) {
  184.             /* not the controlling terminal - oh well */
  185.             /* since we have no controlling terminal, I guess
  186.              * we had better say that we're in the background!
  187.              */
  188.             return TRUE;
  189.         } else { 
  190.             perror("TIOCGPGRP");
  191.             SM_ERROR(TYPE_FATAL, errno);
  192.         }
  193.     } 
  194.     result = (ctermpg  != mypg);
  195.  
  196.     TRPRINT(TR_CL, TR_LEVEL_1, ("%sground", result?"back":"fore"));
  197.     return result;
  198. }
  199.  
  200. static void
  201. dofg(BOOL reopenstdin, BOOL reattach)
  202. {
  203.     /* RunInBackground is set by -background or the terminal "background"
  204.      * command and, if set, perpetually overrides all other factors
  205.      */
  206.     if(RunInBackground) return; /* do nothing */
  207.  
  208.     if(reopenstdin) {
  209.         /* reopen stdin - closes whatever it was... */
  210.         TRPRINT(TR_CL, TR_LEVEL_1, ("reopening, old fd %d", fileno(stdin)));
  211.         freopen("/dev/tty", "r", stdin);
  212.         TRPRINT(TR_CL, TR_LEVEL_1, ("reopened, new fd %d", fileno(stdin)));
  213.         /* set close-on-exec */
  214.         if (fcntl(fileno(stdin), F_SETFD, NULL) < 0)    {
  215.             SM_ERROR(TYPE_FATAL, errno);
  216.         }
  217.         if(reattach) {
  218.             if(ioctl(devttyfd, TIOCSPGRP, &mypg) < 0) {
  219.                 perror("TIOCSPGRP");
  220.             }
  221.         }
  222.     }
  223.     /* restore mask after stdin has a fileno */
  224.     setStdinLink();
  225. }
  226.  
  227. void
  228. dobg(BOOL dodetach)
  229. {
  230.     if(dodetach) {
  231.         TRPRINT(TR_CL, TR_LEVEL_1, ("detaching, ttyfd %d", devttyfd));
  232.         if(ioctl(devttyfd, TIOCSPGRP, &ppid) < 0) {
  233.             perror("TIOCSPGRP");
  234.         }
  235.     }
  236.     TRPRINT(TR_CL, TR_LEVEL_1, ("stdin fd %d", fileno(stdin)));
  237.     if(fileno(stdin) != -1) {
  238.         /* it's open */
  239.         clearStdinLink();
  240.         fclose(stdin);
  241.     }
  242.     /* now it's closed */
  243. }
  244.  
  245. void
  246. cont(int sig, int unused)
  247. {
  248.     static int countTTIN = 0;
  249.     TRPRINT(TR_CL, TR_LEVEL_1, ("cont sig %d", sig));
  250.     if( isbg() ) {
  251.         dobg(FALSE); /* already detached */
  252.     } else {
  253.         countTTIN = 0;
  254.         dofg(TRUE, FALSE);
  255.     }
  256.     if(++countTTIN > 4) {
  257.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  258.     }
  259. }
  260.  
  261. void
  262. startuptty()
  263. {
  264.     if( isbg() ) {
  265.         clearStdinLink();
  266.         /* its fd is already closed, but we want to 
  267.          * clean up the FILE too, so fclose it:
  268.          */
  269.         fclose(stdin); 
  270.     } else {
  271.         /* already open, attached */
  272.         setStdinLink();
  273.     }
  274.     TRPRINT(TR_CL, TR_LEVEL_1, ("stdin fd %d", fileno(stdin)));
  275. }
  276.  
  277.  
  278. void
  279. catchSignals()
  280. {
  281.     extern int errno;
  282.     struct sigvec sv;
  283.     register int i;
  284.  
  285.     TRACE(TR_INIT | TR_CL, TR_LEVEL_1);
  286.     if( (ppid = getppid()) < 0 ) {
  287.         perror("getppid(0)");
  288.     }
  289. #if defined(hpux) || defined(linux)
  290.     if( (mypg = getpgrp()) < 0 ) {
  291.         perror("getpgrp()");
  292.     }
  293. #else
  294.     if( (mypg = getpgrp(0)) < 0 ) {
  295.         perror("getpgrp(0)");
  296.     }
  297. #endif
  298.     if((devttyfd = open("/dev/tty", O_RDONLY, 0))<0) {
  299.         if(errno == ENXIO) {
  300.             /* no such device  - that means whoever
  301.              * forked us did a TIOCNOTTY first - gak
  302.              */
  303.             devttyfd = 0;
  304.             /* that's our best guess. and if it's closed,
  305.              * well, c'est la vie. we won't be able to 
  306.              * do much.
  307.              */
  308.         } else {
  309.             perror("open dev/tty");
  310.             admin_ShutServer(0);
  311.         }
  312.     }
  313.  
  314.     sv.sv_mask = 0; /* or-ed in with mask for current signal */
  315.     sv.sv_flags = 0; /* don't use sigstack */
  316.     
  317.     for(i=1; i<NSIG; i++) {
  318.  
  319.         if (siginfo[i].sig == 0) {
  320.             break;  /* end of list of signals */
  321.         }
  322.  
  323.         /* 
  324.          * Cast to no-arg func so it compiles. Maybes someday someone
  325.          * will fix signal.h to declare sv_handler properly.
  326.          */
  327. #if defined(DOTDOTDOT) || defined(hpux)
  328.         /* Sun C++ defines  DOTDOTDOT */
  329.         if((sv.sv_handler = (void (*)(...))siginfo[i].sv_handler) 
  330.             == (void (*)(...))SIG_DFL)
  331. #elif defined(linux)
  332.         if((sv.sv_handler = (__sighandler_t)siginfo[i].sv_handler) 
  333.             == SIG_DFL)
  334. #else
  335.         if((sv.sv_handler = (void (*)())siginfo[i].sv_handler) 
  336.             == (void (*)())SIG_DFL)
  337. #endif
  338.             continue; /* don't bother */
  339.  
  340. /*
  341.         TRPRINT(TR_INIT | TR_CL, TR_LEVEL_1, ("signal %d gets 0x%x",
  342.             siginfo[i].sig, (void *)(siginfo[i].sv_handler)));
  343. */
  344.  
  345. #ifdef hpux
  346.         if(sigvector(siginfo[i].sig, &sv, 0 /* don't care about old vector */) < 0) {
  347. #else
  348.         if(sigvec(siginfo[i].sig, &sv, 0 /* don't care about old vector */) < 0) {
  349. #endif hpux
  350.             TRPRINT(TR_INIT, TR_LEVEL_1, ("sigvec failure on sig %d",siginfo[i]));
  351.             SM_ERROR(TYPE_FATAL, errno);
  352.         } 
  353.     }
  354. }
  355.  
  356. void
  357. unCatchAbortSignal(
  358.     int sig
  359. )
  360. {
  361.     struct sigvec sv;
  362.  
  363.     TRPRINT(TR_INIT, TR_LEVEL_1, ("sig %d", sig));
  364.     sv.sv_mask = 0; /* or-ed in with mask for current signal */
  365.     sv.sv_flags = 0; /* don't use sigstack */
  366. #if defined(DOTDOTDOT) || defined(hpux)
  367.         /* Sun C++ defines  DOTDOTDOT */
  368.     sv.sv_handler = (void (*)(...))SIG_DFL;
  369. #elif defined(linux)
  370.     sv.sv_handler = SIG_DFL;
  371. #else
  372.     sv.sv_handler = (void (*)())SIG_DFL;
  373. #endif
  374.  
  375. #ifdef hpux
  376.     if(sigvector(sig, &sv, 0 /* don't care about old vector */) < 0) {
  377. #else
  378.     if(sigvec(sig, &sv, 0 /* don't care about old vector */) < 0) {
  379. #endif hpux
  380.         perror("sigvec"); /* to avoid loops we don't call SM_ERROR */
  381.         admin_ShutServer(SHUT_ABNORMAL_EXIT | SHUT_DUMP_CORE);
  382.     }
  383. }
  384.